package com.aliyun.heiyu.powermaster.server.strategy.action;

import com.aliyun.heiyu.common.util.LogUtils;
import com.aliyun.heiyu.common.util.PropertiesUtil;
import com.aliyun.heiyu.common.util.SSHUtil;
import com.aliyun.heiyu.common.util.StringUtil;
import com.aliyun.heiyu.powermaster.server.dao.enums.DeviceUsageStatusEnum;
import com.aliyun.heiyu.powermaster.server.factory.TransDeviceManager;
import com.aliyun.heiyu.powermaster.server.manager.DeviceManager;
import com.aliyun.heiyu.powermaster.server.strategy.StrategyExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class PowerOffAction {
    private static Logger logger = LoggerFactory.getLogger(PowerOffAction.class);

    private static PowerOffAction instance;

    private static final String POWER_OFF = "POWEROFF";
    private static final String POWER_ON = "POWERON";

    private Set<String> devicePool;
    private HashMap<Integer, String> indexMap;
    private int maxinumPooSize;
    private int corePoolSize;
    private int index;
    private List<String> powerOnactionList;
    private List<String> powerOffactionList;
    DeviceManager deviceManager;
    SSHUtil sshUtil;

    public static PowerOffAction getInstance(){
            synchronized (PowerOffAction.class){
                if(instance == null){
                    instance = new PowerOffAction();
                }
            }

        return instance;
    }

    public boolean isExist(String deviceId){
        if (devicePool.contains(deviceId)) {
            return true;
        }
        if (powerOffactionList.contains(deviceId)) {
            return true;
        }
        if(powerOnactionList.contains(deviceId)){
            return true;
        }
        return false;
    }

    //配置文件话 缓存池大小
    private PowerOffAction() {
        //默认大小为4
        int count = 4;
        int size = StringUtil.convertInt(PropertiesUtil.getValue("aiControllerConfig.properties", "power_off_pool_size"));
        count = 0 == size ? 4 : size;
        this.devicePool = new HashSet<>();
        this.indexMap = new HashMap<>();
        this.maxinumPooSize = count;
        this.corePoolSize = count * 8 / 10;
        this.powerOffactionList = new ArrayList<>();
        this.powerOnactionList = new ArrayList<>();
        this.deviceManager = TransDeviceManager.getDeviceServiceTrans();
        this.sshUtil = new SSHUtil("localhost", 22, "root", "AliOS%1688");
        bootAction();
    }

    private PowerOffAction(int count) {
        this.devicePool = new HashSet<>();
        this.indexMap = new HashMap<>();
        this.maxinumPooSize = count;
        this.corePoolSize = count * 8 / 10;
        this.powerOffactionList = new ArrayList<>();
        this.powerOnactionList = new ArrayList<>();
        this.deviceManager = TransDeviceManager.getDeviceServiceTrans();
        this.sshUtil = new SSHUtil("localhost", 22, "root", "AliOS%1688");
    }

    public void inPool(String deviceId) {
        if (deviceId == null || deviceId.isEmpty()) {
            throw new IllegalArgumentException("deviceId exception");
        }
        if (devicePool.contains(deviceId)) {
            return;
        }
        logger.debug("inpool: " + LogUtils.vaildlog(deviceId));
        int size = devicePool.size();
        if (size < maxinumPooSize) {
            devicePool.add(deviceId);
            indexMap.put(index, deviceId);
            index += 1;
        } else {
            powerOffactionList.add(deviceId);
            logger.debug("the cache pool is full，count is " + maxinumPooSize + ",so put device:" + LogUtils.vaildlog(deviceId) + " in powerOffactionList");
        }
        logger.debug("devicepool ==  "+devicePool);
    }

    public void outPool(String deviceId) {
        if (deviceId == null || deviceId.isEmpty()) {
            throw new IllegalArgumentException("deviceId exception");
        }
        logger.debug("outpool: " + LogUtils.vaildlog(deviceId));
        if(powerOnactionList.contains(deviceId)){
            boolean bool = powerAction(deviceId, POWER_ON);
            if(bool){
                powerOnactionList.remove(deviceId);
            }
        } else if(powerOffactionList.contains(deviceId)){
            powerOffactionList.remove(deviceId);
        } else {
            devicePool.remove(deviceId);
        }

    }


    private boolean powerAction(String deviceId, String powerAction) {
        Map<String, String> device = deviceManager.findOneDeviceDetail(deviceId);
        if (device == null) {
            logger.error("this device has been deleted");
            return false;
        }
        String oob_ip = device.get("oob_ip");
        if (oob_ip == null || oob_ip.isEmpty()) {
            logger.error("the oob_ip of this device is null or empty");
            return false;
        }
        String s1 = "ipmitool -H ";
        String s2 = " -U admin -P admin ";
        String s3 = "power off ";
        String s4 = "power on ";
        StringBuffer action = new StringBuffer();
        action.append(s1).append(oob_ip).append(s2);
        String result = null;
        switch (powerAction) {
            case POWER_OFF:
                action.append(s3);
                logger.debug(LogUtils.vaildlog(action.toString()));
                result = sshUtil.exeCommand(action.toString());
                break;
            case POWER_ON:
                action.append(s4);
                logger.debug(LogUtils.vaildlog(action.toString()));
                result = sshUtil.exeCommand(action.toString());
                break;
            default:
                return false;
        }
        if (result != null) {
            logger.debug(LogUtils.vaildlog(deviceId) + " " + LogUtils.vaildlog(powerAction) + " success");
            return true;
        }
        logger.error("ipmi control failed");
        return false;
    }

    private void bootAction() {
        StrategyExecutor.getInstance().getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    int size = powerOffactionList.size();
                    if (size > 0) {
                        logger.debug("will shutdown:" + powerOffactionList);
                        for (int i = size - 1; i >= 0; i--) {
                            String deviceId = powerOffactionList.get(i);
                            //执行powerOff
                            boolean bool = powerAction(deviceId, POWER_OFF);
                            if (bool) {
                                deviceManager.modifyUsageStatus(deviceId, DeviceUsageStatusEnum.DEVICE_POWEROFF.getMsg());
                                powerOffactionList.remove(deviceId);
                                powerOnactionList.add(deviceId);
                            }
                        }
                    }
                    if (devicePool.size() < corePoolSize && powerOnactionList.size() > 0) {
                        String deviceId = powerOnactionList.get(0);
                        logger.debug("will startup:" + LogUtils.vaildlog(deviceId));
                        //执行powerOn
                        boolean bool = powerAction(deviceId, POWER_ON);
                        if (bool) {
                            deviceManager.modifyUsageStatus(deviceId, DeviceUsageStatusEnum.DEVICE_NORMAL_USE.getMsg());
                            devicePool.add(deviceId);
                            powerOnactionList.remove(deviceId);
                        }
                    }
                    logger.debug("devicePool:" + devicePool);
                    logger.debug("powerOffactionList:" + powerOffactionList);
                    logger.debug("powerOnactionList:" + powerOnactionList);
                    try {
                        Thread.sleep(1000 * 60);
                    } catch (InterruptedException e) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
        });
    }

}
